package com.sky.canal;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sky.constant.RedisConstant;
import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.service.IDishFlavorService;
import com.sky.service.IDishService;
import com.sky.utils.RedisCacheUtil;
import com.sky.vo.DishVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @BelongsProject: sky-take-out
 * @Author: XieMingHui
 * @CreateTime: 2023-11-27  15:08
 * @Description: 菜品分类canal监听器
 * @Version: 1.0
 */
@CanalTable("dish")
@Component
@Slf4j
public class DishCanal implements EntryHandler<Dish> {

    @Resource
    private RedisCacheUtil redisCacheUtil;
    @Resource
    private IDishService iDishService;
    @Resource
    private IDishFlavorService dishFlavorService;
    /**
     * 有新增
     * @author: XieMingHui
     * @param: [category]
     * @return: void
     **/
    @Override
    public void insert(Dish dish) {
        log.info("数据库中新增的数据:{}",dish);
        //得到菜品类型的id
        Long categoryId = dish.getCategoryId();
        // 查数据库,更新redis
        getDataSaveRedis(categoryId);
    }
    /**
     * 有新增
     * @author: XieMingHui
     * @param: [category]
     * @return: void
     **/
    @Override
    public void update(Dish before, Dish after) {
        log.info("数据库中更新前的数据:{}更新后的数据:{}",before,after);
        //得到菜品类型的id
        Dish dish = iDishService.getById(after.getId());
        // 查数据库,更新redis
        getDataSaveRedis(dish.getCategoryId());
    }
    /**
     * 有新增
     * @author: XieMingHui
     * @param: [category]
     * @return: void
     **/
    @Override
    public void delete(Dish dish) {
        log.info("数据库中删除的数据:{}",dish);
        //得到菜品类型的id
        Long categoryId = dish.getCategoryId();
        // 查数据库,更新redis
        getDataSaveRedis(categoryId);
    }

    // 查数据库,更新redis
    private void getDataSaveRedis(Long categoryId) {
        String key = RedisConstant.CATEGORY_KEY+ categoryId;
        //查询该菜品类型下所有菜品,重新更新缓存
        List<DishVO> listVO = getDishVOS(categoryId);
        //更新redis中逻辑过期字段
        redisCacheUtil.setRedis(key, listVO, RedisConstant.LOGIC_TIME, TimeUnit.DAYS);
    }

    /**
     * 数据库查询对应菜品类型所有菜品和菜品对应口味的方法
     *
     * @author: XieMingHui
     * @param: [categoryId]
     * @return: java.util.List<com.sky.vo.DishVO>
     **/
    private List<DishVO> getDishVOS(Long categoryId) {
        // 根据分类id查询起售中的菜品
        List<Dish> dishList =iDishService.lambdaQuery()
                .eq(categoryId != null, Dish::getCategoryId, categoryId)
                .eq(Dish::getStatus, StatusConstant.ENABLE)
                .list();
        // 封装VO
        List<DishVO> listVO = new ArrayList<>(dishList.size());
        // 封装菜品id
        List<Long> listDishId = new ArrayList<>(dishList.size());
        for (Dish dish : dishList) {
            listVO.add(BeanUtil.toBean(dish, DishVO.class));
            listDishId.add(dish.getId());
        }
        //用id查询菜品口味
        List<DishFlavor> dishFlavorList = dishFlavorService.lambdaQuery()
                .in(DishFlavor::getDishId, listDishId)
                .list();
        // 封装到菜品中
        EncapsulationFlavor(listVO, dishFlavorList);
        return listVO;
    }

    /**
     * 封装菜品口味到菜品中
     *
     * @author: XieMingHui
     * @param: [listVO, dishFlavorList]
     * @return: void
     **/
    private void EncapsulationFlavor(List<DishVO> listVO, List<DishFlavor> dishFlavorList) {
        Map<Long, DishVO> dishVOMap = listVO.stream().collect(Collectors.toMap(DishVO::getId, v -> v));
        for (DishFlavor dishFlavor : dishFlavorList) {
            DishVO dishVO = dishVOMap.get(dishFlavor.getDishId());
            if (dishVO != null) {
                dishVO.getFlavors().add(dishFlavor);
            }
        }
    }
}
